home *** CD-ROM | disk | FTP | other *** search
- /*
- * RevRINIT.c - INIT to cause RevRdist to be run at system boot time
- */
- #include <MacProto.h>
- #include <C_config.h>
- #include <asm.h>
- #include <HFS.h>
- #include "HyperXCmd.h"
- #include "rsrc.h"
-
- /*
- * Structure of startup header
- */
- typedef unsigned char Str15[16]; /* short pascal string */
- struct startp {
- Integer startid; /* id word */
- ProcPtr entryp; /* boot code entry point */
- Integer version; /* startup version */
- Integer azero;
- Str15 sysname; /* name of system resource file */
- Str15 shellname; /* name of system shell */
- Str15 debuggername; /* name of debugger file */
- Str15 disassmname; /* name of disassembler file */
- Str15 startscreen; /* name of startup screen image file */
- Str15 startappl; /* name of first program to run */
- Str15 scrapname; /* name of disk scrap file */
- Integer fcbcnt; /* number of file control blocks */
- Integer eventcnt; /* size of event queue */
- Longint heapsize1; /* heap size on 128k system */
- Longint reserved;
- Longint heapsize2; /* heap size on 512k system */
- };
- typedef struct startp startp_t;
- #define STARTID 'LK' /* correct value of id word */
-
- typedef unsigned char Str31[32]; /* path name component */
- typedef unsigned long u_long;
-
- #define COPYPS(s,d) BlockMove (s, d, (Size)(((s)[0]) + 1)) /* copy pas. str */
- #define ZERO(s) setmem ((char *)&(s), sizeof (s), 0) /* zero struct */
-
- /*
- * Prototypes
- */
- pascal void callback (void);
- static OSErr doFudge (Str31);
- static OSErr findAppl (Str31);
- static OSErr getPrefs (Str31, StringHandle *, Str31, Str31, Str31, Str31, Str31);
- static OSErr getPrefsName (Str31, Str31);
- extern void main (Handle);
- static OSErr mountsvr (Str31, Str31, Str31, Str31, Str31);
- static Handle ptoch (unsigned char *);
- extern void setmem (char *p, unsigned n, char c);
- extern void ShowINIT (Integer);
- static void start (void);
-
-
- /*
- *=========================================================================
- * start () - routine given control by INIT 31
- * Must be first code in first file in project
- *=========================================================================
- */
- static
- void
- start ()
- {
- asm
- {
- move.l a0,-(sp) /* pass handle to selves to main */
- move.l (a0),a4 /* set A4 to allow refs to globals */
- jsr main /* call main routine */
- move.l (sp)+,a0 /* pop arg to restore stack */
- }
- }
-
-
- extern unsigned char ApplScratch[12] : 0xa78;
-
- /*
- *=========================================================================
- * main - main sequence
- *=========================================================================
- */
- void
- main (self)
- Handle self;
- {
- register OSErr result;
- StringHandle master; /* name of master folder on server */
- Str31 applName; /* name of RevRdist application */
- Str31 prefName; /* name of prefs file */
- Str31 zoneName; /* server zone name */
- Str31 serverName; /* name of server to use */
- Str31 userName; /* name to log on to server as */
- Str31 serverVol; /* server volume to user */
- Str31 password; /* user password on server */
- CInfoPBRec ci; /* for PBGetCatInfo call */
- Str255 s; /* string temp */
- Integer volref; /* dummy for GetVol */
-
- HLock (self);
- SetResLoad (true); /* should already be true, but ... */
- result = (FSFCBLen <= 0); /* make sure HFS */
- /*
- * Find the RevRdist application
- */
- if (result == 0)
- result = findAppl (applName);
- /*
- * Get the name of the preferences file from RevRdist
- */
- if (result == 0)
- result = getPrefsName (applName, prefName);
- /*
- * Extract the preferences & check if it's time to run
- */
- master = 0;
- if (result == 0)
- result = getPrefs (prefName, &master,
- serverVol, zoneName, serverName, userName, password);
- /*
- * If the master folder is not currently available, try to mount it
- */
- if (result == 0)
- {
- ZERO (ci);
- HLock ((Handle) master);
- ci.dirInfo.ioNamePtr = *master;
- result = PBGetCatInfo (&ci, false);
- HUnlock ((Handle) master);
- if (result
- || (ci.dirInfo.ioFlAttrib & 0x10) == 0 /* if not folder */
- || (ci.dirInfo.ioACUser & 0x03) != 0 ) /* if no access */
- {
- /*
- * Be sure we don't try to unmount the boot volume
- */
- (void) GetVol (s, &volref);
- if (RelString (s, serverVol, false, true))
- {
- serverVol[++serverVol[0]] = ':';
- (void) UnmountVol (serverVol, 0);
- serverVol[0]--;
- result = mountsvr (serverVol, zoneName, serverName, userName, password);
- }
- else
- result = paramErr;
- }
- }
- if (master)
- DisposHandle ((Handle) master);
- if (result == 0)
- result = doFudge (applName);
- HUnlock (self);
- }
-
-
-
- /*
- *=========================================================================
- * callback () - dummy XCMD callback routine
- * should never be called
- *=========================================================================
- */
- pascal
- void
- callback ()
- {
- }
-
-
-
- /*
- *=========================================================================
- * doFudge (ap) - modify memory copy of boot blocks to make RevRdist
- * application the "startup" application
- * entry: ap = name of RevRdist
- * returns: 0 if all went well,
- * <> 0 if boot blocks area looks fishy
- *=========================================================================
- */
- static
- OSErr
- doFudge (ap)
- Str31 ap;
- {
- register unsigned char c;
- register startp_t * startp; /* ptr to boot param block */
- long * lp; /* pts into ApplScratch */
-
- /*
- * Locate the memory copy of the system startup information
- * Check that it appears intact.
- * Replace the startup program name with RevRdist name
- */
- startp = (startp_t *) ((long)MemTop / 2);
-
- if (startp->startid != STARTID)
- return 1;
- if (startp->azero)
- return 2;
- #define CHECK(w, e) if ((c = startp->w[0]) == 0 || c > 15) return (e)
- CHECK (sysname, 3);
- CHECK (shellname, 4);
- CHECK (debuggername, 5);
- CHECK (disassmname, 6);
- CHECK (startscreen, 7);
- CHECK (startappl, 8);
- CHECK (scrapname, 9);
- #undef CHECK
- if (startp->fcbcnt < 0)
- return 10;
- if (startp->eventcnt < 0)
- return 11;
- COPYPS (ap, startp->startappl);
- lp = (long *)(ApplScratch + 8);
- lp[0] = CREATOR; /* leave a "note" for RevRdist */
- return 0;
- }
-
-
-
- /*
- *=========================================================================
- * findAppl (ap) - locate RevRdist application and return its name
- * entry: ap = Str31 to contain name
- * returns: 0 on success, else OSErr
- *=========================================================================
- */
- static
- OSErr
- findAppl (ap)
- Str31 ap;
- {
- OSErr error;
- int i;
- Str255 name;
- CInfoPBRec ci;
-
- /*
- * Search the current directory to find a file with the correct
- * type (APPL) and CREATOR.
- */
- ZERO (ci);
- ci.hFileInfo.ioNamePtr = name;
- for (i = 1, error = 0; ! error; i++)
- {
- name[0] = 0;
- ci.hFileInfo.ioDirID = 0;
- ci.hFileInfo.ioFDirIndex = i;
- error = PBGetCatInfo (&ci, false);
- if (error == 0)
- {
- if (ci.hFileInfo.ioFlAttrib & 0x10)
- continue; /* if directory */
- if (ci.hFileInfo.ioFlFndrInfo.fdType == 'APPL'
- && ci.hFileInfo.ioFlFndrInfo.fdCreator == CREATOR)
- {
- if (name[0] > 15)
- continue; /* ignore if unacceptable name */
- COPYPS (name, ap);
- break;
- }
- }
- }
- return error;
- }
-
-
-
- /*
- *=========================================================================
- * getPrefs (pf, mf, sv, zn, sn, un, pw) - extract info from preferences file
- * entry: pf = name of preferences file
- * mf = ptr to handle for master folder name string
- * sv = buf for server volume name
- * zn = buf for server zone
- * sn = buf for server name
- * un = buf for user name
- * pw = buf for password
- * returns: 0 if preferences found and set,
- * <> 0 on error
- *=========================================================================
- */
- static
- OSErr
- getPrefs (pf, mf, sv, zn, sn, un, pw)
- Str31 pf;
- StringHandle * mf;
- Str31 sv;
- Str31 zn;
- Str31 sn;
- Str31 un;
- Str31 pw;
- {
- Integer curref; /* current resource file */
- OSErr error;
- Handle h; /* handle to resources */
- int i; /* temp counter */
- u_long now; /* current time */
- u_long interval; /* running interval from prefs */
- Handle ph; /* handle to interval resource */
- Integer refnum; /* resource file refnum */
- StringPtr sp, tp; /* ptrs to resource strings */
- Integer vrefnum; /* resource file vrefnum */
- HParamBlockRec pb; /* HFS parameter block */
- Str255 s; /* temp copy of string */
-
- /*
- * Extract the various preference resources from the preferences file
- */
- error = 0;
- curref = CurResFile ();
- refnum = OpenRFPerm (pf, 0, fsRdWrPerm);
- if (refnum == -1)
- return ResError ();
- /*
- * First get the interval.
- * If it's not time to run yet, exit
- */
- ph = Get1Resource (TYPE_LONG, TIME_INTERVAL);
- if (!ph)
- goto resexit;
- if (SizeResource (ph) < sizeof (interval))
- {
- error = resNotFound;
- goto exit;
- }
- interval = *(u_long *)(*ph);
- GetDateTime ((long *)&now);
- error = GetVRefNum (refnum, &vrefnum);
- if (error)
- goto exit;
- ZERO (pb);
- pb.fileParam.ioNamePtr = pf;
- pb.fileParam.ioVRefNum = vrefnum;
- error = PBHGetFInfo (&pb, false);
- if (error)
- goto exit;
- if ((u_long) pb.fileParam.ioFlMdDat + interval > now)
- {
- error = 1; /* not time yet */
- goto exit;
- }
-
- /*
- * Go ahead and extract the remaining preference strings
- */
- h = Get1Resource ('STR ', STR_MASTF);
- if (!h)
- goto resexit;
- /*
- * The master folder STR is a complete path.
- * We also want the first component.
- */
- sp = (StringPtr)(*h);
- COPYPS (sp, s);
- for (i = s[0]; i > 0; i--)
- if (s[i] == ':')
- s[0] = i-1;
- if (s[0] > 31)
- goto badstring;
- *mf = (StringHandle) h;
- DetachResource(h);
- COPYPS (s, sv);
-
- h = Get1Resource ('STR ', STR_ZONE);
- if (h) /* zone is optional */
- {
- sp = (StringPtr)(*h);
- if (sp[0] > 31)
- goto badstring;
- COPYPS (sp, zn);
- ReleaseResource (h);
- }
- else
- zn[0] = 0;
-
- h = Get1Resource ('STR ', STR_SRVR);
- if (!h)
- goto resexit;
- sp = (StringPtr)(*h);
- if (sp[0] > 31)
- goto badstring;
- COPYPS (sp, sn);
- ReleaseResource (h);
-
- h = Get1Resource ('STR ', STR_USER);
- if (h) /* user is optional */
- {
- sp = (StringPtr)(*h);
- if (sp[0] > 31)
- goto badstring;
- COPYPS (sp, un);
- ReleaseResource (h);
- }
- else
- un[0] = 0;
-
- h = Get1Resource ('STR ', STR_PASS);
- if (h) /* password is optional */
- {
- sp = (StringPtr)(*h);
- if (sp[0] > 31)
- goto badstring;
- COPYPS (sp, pw);
- ReleaseResource (h);
- }
- else
- pw[0] = 0;
- /*
- * "Change" a resource to update the mod time so we don't
- * get in a boot/run/reboot loop
- */
- ChangedResource (ph);
- WriteResource (ph);
- goto exit;
-
- resexit:
- error = ResError ();
- if (!error)
- error = resNotFound;
- goto exit;
-
- badstring:
- ReleaseResource (h);
- error = bdNamErr;
-
- exit:
- if (ph)
- ReleaseResource (ph);
- if (refnum != curref)
- {
- (void) CloseResFile (refnum);
- (void) UseResFile (curref);
- }
- return error;
- }
-
-
-
-
- /*
- *=========================================================================
- * getPrefsName (ap, pf) - extract preferences file name from appl file
- * entry: ap = name of RevRdist application in current directory
- * pf = buf for prefs file name
- * returns 0 if pf set,
- * <> 0 on error
- *=========================================================================
- */
- static
- OSErr
- getPrefsName (ap, pf)
- Str31 ap;
- Str31 pf;
- {
- Integer curref; /* current resource file */
- OSErr error;
- Handle h;
- Integer refnum; /* resource file refnum */
- StringPtr sp;
-
- /*
- * We just extract the STR_PREFS resource from the RevRdist
- * application to get the name of the its default preferences file.
- */
- error = 0;
- curref = CurResFile ();
- refnum = OpenRFPerm (ap, 0, fsRdPerm);
- if (refnum == -1)
- return (ResError ());
- h = Get1Resource ('STR ', STR_PREFS);
- if (h)
- {
- sp = (StringPtr)(*h);
- if (sp[0] < 32)
- {
- COPYPS (sp, pf);
- ReleaseResource (h);
- ShowINIT (RSRC_INITICON);
- }
- else
- error = bdNamErr;
- }
- else
- error = ResError ();
- if (refnum != curref)
- {
- (void) CloseResFile (refnum);
- (void) UseResFile (curref);
- }
- return error;
- }
-
-
-
-
- /*
- *=========================================================================
- * mountsvr (sv, zn, sn, un, pw) - make sure server volume is mounted
- * entry: sv = name of desired server volume
- * zn = AppleShare zone of server
- * sn = AppleShare name of server node
- * un = user name to use to log into node
- * pw = password for login
- * returns: 0 if volume mounted
- * <> 0 on error
- *=========================================================================
- */
- static
- OSErr
- mountsvr (sv, zn, sn, un, pw)
- Str31 sv;
- Str31 zn;
- Str31 sn;
- Str31 un;
- Str31 pw;
- {
- OSErr error;
- register Handle h; /* temp handle */
- int i, j; /* temp index */
- int pass; /* try counter */
- Handle xh; /* handle to XCMD */
- XCmdBlock cb; /* XCMD parameter block */
- HParamBlockRec pb; /* HFS parameter block */
- Str255 name;
-
- h = (Handle) 2; /* set non-zero */
- for (pass = 1; pass <= 2; pass++)
- {
- /*
- * Scan the mounted volumes looking for the server volume
- */
- ZERO (pb);
- pb.volumeParam.ioNamePtr = name;
- for (i = 1, error = 0; ! error; i++)
- {
- name[0] = 0;
- pb.volumeParam.ioVRefNum = 0;
- pb.volumeParam.ioVolIndex = i;
- error = PBHGetVInfo (&pb, false);
- if (RelString (sv, name, false, true) == 0)
- return 0; /* found it */
- }
- /*
- * Searched all volumes without finding it.
- * Use the Apple Mount XCMD to try to mount the volume from
- * an AppleShare server.
- */
- xh = GetResource ('XCMD', RSRC_MOUNT);
- if (! xh)
- return (ResError ());
- ZERO (cb);
- /*
- * Set calling arg list into XCMD param block
- */
- error = memFullErr;
- i = 0;
- cb.params[i++] = h = ptoch (zn); /* zone */
- if (!h)
- goto failed;
- cb.params[i++] = h = ptoch (sn); /* server */
- if (!h)
- goto failed;
- cb.params[i++] = h = ptoch (sv); /* volume */
- if (!h)
- goto failed;
- if (un[0]) /* user, if not empty */
- {
- cb.params[i++] = h = ptoch (un);
- if (!h)
- goto failed;
- if (pw[0]) /* password, if not empty */
- {
- cb.params[i++] = h = ptoch (pw);
- if (!h)
- goto failed;
- }
- }
- error = 0;
- cb.paramCount = i;
- cb.entryPoint = (ProcPtr) callback;
- HLock (xh);
- (*(ProcPtr)(*xh)) (&cb); /* call the XCMD */
- /*
- * dispose of our strings, etc.
- */
- HUnlock (xh);
- failed:
- for (--i; i >= 0; --i)
- DisposHandle (cb.params[i]);
- h = cb.returnValue; /* check the result */
- if (h && *h && **h)
- error = fnfErr;
- if (cb.returnValue)
- DisposHandle (cb.returnValue);
- ReleaseResource (xh);
- if (error)
- break;
- }
- return error;
- }
-
-
-
- /*
- *=========================================================================
- * ptoch (ps) - copy pascal string to c string in new handle
- * entry: ps = ptr to pascal string
- * returns: handle to null-terminated copy of string
- * 0 if cannot allocate handle
- *=========================================================================
- */
- static
- Handle
- ptoch (ps)
- register unsigned char *ps;
- {
- register Handle h;
- register int i;
- register unsigned char *s;
-
- i = ps[0];
- h = NewHandle ((Size) (i + 1));
- if (h)
- {
- for (s = (unsigned char *)(*h); i; i--)
- *s++ = *++ps;
- *s = 0;
- }
- return h;
- }